home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 2000 October: Mac OS SDK / Dev.CD Oct 00 SDK1.toast / Development Kits / Mac OS / Multiprocessing 2.1v2 SDK / Sample Code / CloseViewMP ƒ / .c / CloseViewMP.c next >
Encoding:
C/C++ Source or Header  |  2000-05-25  |  12.1 KB  |  606 lines  |  [TEXT/CWIE]

  1. /**\
  2. |**|    CloseViewMP.c
  3. \**/
  4.  
  5. #include "CloseViewMP.h"
  6.  
  7. // typdef's, struct's, define's, enum's, etc.
  8.  
  9. #define kMPStackSize 0        // use default stack size
  10. #define kMPTaskOptions 0    // use no options
  11.  
  12. typedef struct MyTaskStruct {
  13.     MPTaskID        fTaskID;
  14.     MPTaskWeight    fWeight;
  15. }MyTaskRec,*MyTaskPtr,**MyTaskHdl;
  16.  
  17. typedef struct MyGDInfo {
  18.     GDHandle        fGDHdl;
  19.     PixMapHandle    fPixMapHdl;
  20.     Ptr                fBaseAddr;
  21.     Rect            fRect;
  22. }MyGDInfoRec,*MyGDInfoPtr,**MyGDInfoHdl;
  23.  
  24. // external globals
  25.  
  26. UInt32        gMag = 1;
  27.  
  28. // local (static) globals & const
  29.  
  30. static Boolean         gPaused = false;
  31. static Boolean         gLoop = true;
  32.  
  33. #if !SMP_TEST
  34. static MPQueueID         gNotificationQueueID;
  35. static MyTaskRec         gMyTaskRec;
  36. static MPSemaphoreID    gSemaphoreID;
  37. #endif !SMP_TEST
  38.  
  39. static MenuHandle gContextualMenuHdl = nil;
  40.  
  41. static const SInt16 gMags[] = {25,50,100,200,400,800,1600,3200,6400,9999};
  42.  
  43. static Point gMidPoint = {-1,-1};
  44.  
  45. static Rect gSrcRect = {-1,-1,-1,-1};
  46. static Rect gDstRect = {-1,-1,-1,-1};
  47.  
  48. static PixMapHandle gSrcPixMapHdl = nil;
  49. static PixMapHandle gDstPixMapHdl = nil;
  50.  
  51. static Ptr gSrcBaseAddr = nil;
  52. static Ptr gDstBaseAddr = nil;
  53.  
  54. static MyGDInfoRec gMyGDInfoRec[8];    // nobody's got more than 8 monitors
  55.  
  56. // local function prototypes
  57. static OSStatus MyTask(void* pMyTaskPtr);
  58. static void Blit_All(void);
  59. static void Blit_One(const Rect* pSrcRect,const Rect* pDstRect);
  60.  
  61. static Boolean Point2_In_Rect(const short pH,const short pV,const Rect* pRect);
  62. static Boolean Intersect_Rects(const Rect* pRect1,Rect* pRect2);
  63. static void Set_Rect(
  64.     Rect *r,
  65.     const short pLeft,
  66.     const short pTop,
  67.     const short pRight,
  68.     const short pBottom);
  69.  
  70. static void Offset_Rect(Rect *r,const short pDh,const short pDv);
  71.  
  72. static SInt16 random();
  73.  
  74. #define ABS(x) ((x) < 0 ? -(x) : (x))
  75.  
  76. // local functions
  77.  
  78. /**\
  79. |**|    Initialize everything for CloseViewMP, make sure we can run
  80. \**/
  81.  
  82. OSStatus CVMP_Init(UInt32 pMag)
  83. {
  84.     OSStatus    error;
  85.  
  86.     if (!MPLibraryIsLoaded())
  87.         return kMPInsufficientResourcesErr;
  88.  
  89.     CVMP_Reset();
  90.  
  91.     // Initialize remaining globals
  92.     gNotificationQueueID = NULL;
  93.     gMag = pMag;
  94.  
  95.     // create the notification queue            
  96.     error = MPCreateQueue(&gNotificationQueueID);
  97.     if (error != noErr)
  98.         return error;
  99.  
  100.     // create the task
  101.     {
  102.         gMyTaskRec.fWeight = 100;
  103.  
  104. #    if !SMP_TEST
  105.         error = MPCreateTask(MyTask, &gMyTaskRec,    // task entry point & parameter
  106.             kMPStackSize, gNotificationQueueID,        // stack size & notification queue ID
  107.             &gMyTaskRec, NULL, kMPTaskOptions,        // Notify params 1 & 2 and task options
  108.             &gMyTaskRec.fTaskID);                    // task id
  109.         if (error != noErr)
  110.         {
  111.             DebugStr("\p|CVMP_Init-F-MPCreateTask error.;g");
  112.             return error;
  113.         }
  114.  
  115.         error = MPSetTaskWeight(gMyTaskRec.fTaskID,gMyTaskRec.fWeight);
  116.         if (error != noErr)
  117.         {
  118.             DebugStr("\p|CVMP_Init-F-MPSetTaskWeight error.;g");
  119.             return error;
  120.         }
  121.  
  122.         // create the work semaphore            
  123.         error = MPCreateSemaphore(256, 0, &gSemaphoreID);
  124.         if (error != noErr)
  125.         {
  126.             DebugStr("\p|CVMP_Init-F-MPCreateSemaphore error.;g");
  127.             return error;
  128.         }
  129. #    endif !SMP_TEST
  130.     }
  131.  
  132. //    gContextualMenuHdl = GetMenu(mWeightMenu);
  133. //    InsertMenu(gContextualMenuHdl, -1);
  134.  
  135.     return error;
  136. }    // CVMP_Init
  137.  
  138. /**\
  139. |**|    Cleanup everything
  140. \**/
  141.  
  142. void CVMP_Term(void)
  143. {
  144.     OSStatus error;
  145.  
  146.     gPaused = gLoop = false;
  147.  
  148.     if (gMyTaskRec.fTaskID != NULL)
  149.     {
  150.         // terminate this task
  151.         error = MPTerminateTask(gMyTaskRec.fTaskID, kMPTaskAbortedErr);
  152. //        if (error != noErr)
  153. //            DebugStr("\p|CVMP_Term-F-MPTerminateTask error.;");
  154.  
  155.         // Now wait for notification that this task has terminated
  156.         while ((error = MPWaitOnQueue(gNotificationQueueID,
  157.             NULL, NULL, NULL, kDurationImmediate)) == noErr)
  158.         {
  159.             if (gMyTaskRec.fTaskID != NULL)
  160.                 gMyTaskRec.fTaskID = NULL;
  161.         }
  162.     }
  163.  
  164.     // delete the notification queue
  165.     if (gNotificationQueueID != NULL)
  166.     {
  167.         MPDeleteQueue(gNotificationQueueID);
  168.         gNotificationQueueID = NULL;
  169.     }
  170. }
  171.  
  172. /**\
  173. |**|    Handle a null event
  174. \**/
  175.  
  176. void CVMP_DoNull(void)
  177. {
  178.     CVMP_Reset();
  179. # if SMP_TEST
  180.     gLoop = false;
  181.     MyTask((void*) &gMyTaskRec);
  182. # else
  183. //    MPYield();
  184. # endif SMP_TEST
  185. }
  186.  
  187. /**\
  188. |**|    Handle a mouse down event
  189. \**/
  190.  
  191. void CVMP_DoClick(const EventRecord *pEventPtr)
  192. {
  193.     Point where = pEventPtr->where;
  194.  
  195.     GlobalToLocal(&where);
  196.  
  197.     SysBeep(15);
  198. }
  199.  
  200. /**\
  201. |**|    set mag
  202. \**/
  203.  
  204. UInt16 CVMP_SetMag(UInt16 pMag)
  205. {
  206.     UInt16 result = gMag;
  207.     gMag = pMag;
  208.  
  209.     CVMP_Reset();
  210.  
  211.     return result;
  212. }
  213.  
  214. /**\
  215. |**|    get mag
  216. \**/
  217.  
  218. UInt16 CVMP_GetMag(void)
  219. {
  220.     return gMag;
  221. }
  222.  
  223. /**\
  224. |**|    set weight
  225. \**/
  226.  
  227. void CVMP_SetWeight(UInt16 pIndex)
  228. {
  229.     if ((pIndex > 0) && (pIndex <= 10))
  230.     {
  231.         OSErr error;
  232.  
  233.         gMyTaskRec.fWeight = gMags[pIndex];
  234.  
  235.         error = MPSetTaskWeight(gMyTaskRec.fTaskID, gMyTaskRec.fWeight);
  236.         if (error != noErr)
  237.             DebugStr("\p|CVMP_SetMag-F-MPSetTaskWeight error.;g");
  238.     }
  239.     else
  240.         SysBeep(15);
  241. }
  242.  
  243. void CVMP_SetMidPoint(Point pPoint)
  244. {
  245.     if (gWindowPtr && !EqualPt(pPoint,gMidPoint))
  246.     {
  247.         gMidPoint = pPoint;
  248.  
  249.         CVMP_Reset();
  250.     }
  251. }
  252.  
  253. /**\
  254. |**|    Reset the mag info
  255. \**/
  256.  
  257. void CVMP_Reset(void)
  258. {
  259.     GDHandle    nthDevice;
  260.     UInt32        index = 0;
  261.  
  262.     gPaused = true;                // pause blitter
  263.     gDstRect = gWindowRect;
  264.  
  265.     for (nthDevice = DMGetFirstScreenDevice(true);nthDevice;
  266.         nthDevice = DMGetNextScreenDevice(nthDevice,true))
  267.     {
  268.         gMyGDInfoRec[index].fGDHdl = nthDevice;
  269.         gMyGDInfoRec[index].fPixMapHdl = (*nthDevice)->gdPMap;
  270.         gMyGDInfoRec[index].fBaseAddr = GetPixBaseAddr(gMyGDInfoRec[index].fPixMapHdl);
  271.         gMyGDInfoRec[index].fRect = (*nthDevice)->gdRect;
  272.         index++;
  273.     }
  274.  
  275.     // zero the rest of the records
  276.     for (;index < 8;index++)
  277.     {
  278.         gMyGDInfoRec[index].fGDHdl = nil;
  279.         gMyGDInfoRec[index].fPixMapHdl = nil;
  280.         gMyGDInfoRec[index].fBaseAddr = nil;
  281.     }
  282.     gLoop = true;
  283.     if (gWindowPtr)
  284.     {    // if the window is unobscured
  285.         static RgnHandle visRgn = nil;
  286.         static RgnHandle contRgn = nil;
  287.  
  288.         if (nil == visRgn)
  289.             visRgn = NewRgn();
  290.  
  291.         if (nil == contRgn)
  292.             contRgn = NewRgn();
  293.  
  294.         if (visRgn && contRgn)
  295.         {
  296. #if TARGET_API_MAC_CARBON
  297.             Rect visRect,contRect;
  298.  
  299.             GetWindowRegion(gWindowPtr,kWindowContentRgn,contRgn);
  300.             GetPortVisibleRegion(GetWindowPort(gWindowPtr),visRgn);
  301.  
  302.             GetRegionBounds(contRgn,&contRect);
  303.             GetRegionBounds(visRgn,&visRect);
  304.  
  305.             OffsetRgn(visRgn,contRect.left - visRect.left,contRect.top - visRect.top);
  306. #else
  307.             CopyRgn(((WindowPeek) gWindowPtr)->contRgn,contRgn);
  308.             CopyRgn(gWindowPtr->visRgn,visRgn);
  309.  
  310.             OffsetRgn(visRgn,
  311.                 (*contRgn)->rgnBBox.left - (*visRgn)->rgnBBox.left,
  312.                 (*contRgn)->rgnBBox.top - (*visRgn)->rgnBBox.top);
  313. #endif TARGET_API_MAC_CARBON
  314.  
  315.             if (EqualRgn(visRgn,contRgn))
  316.                 gPaused = false;    // unpause blitter
  317.         }
  318.         CVMP_Update();
  319.     }
  320. }
  321.  
  322. /**\
  323. |**|    This causes the blit task to break out of its slumber.
  324. \**/
  325.  
  326. void CVMP_Update(void)
  327. {
  328. #if !SMP_TEST
  329.     MPSignalSemaphore(gSemaphoreID);
  330. #endif
  331. }
  332.  
  333. /**\
  334. |**|    set & return the paused state
  335. \**/
  336.  
  337. extern Boolean CVMP_Pause(Boolean pPaused)
  338. {
  339.     Boolean result = gPaused;
  340.     gPaused = pPaused;
  341.  
  342.     return result;
  343. }
  344.  
  345. /**\
  346. |**|    This is the MP task entrypoint
  347. \**/
  348.  
  349. static OSStatus MyTask(void* pMyTaskPtr)
  350. {
  351.     Point oldMousePoint = {-1,-1},mousePoint;
  352.     (pMyTaskPtr);    // #pragma unused (pMyTaskPtr)
  353.  
  354.     //    Blit the data periodically but at a low refresh rate. the main task
  355.     //    will signal if it has demand blitting to do.
  356.     do {
  357.         Blit_All();
  358.         
  359.         do {
  360.             SInt32 index;
  361.             
  362.             for (index = 0;index < 12;index++)
  363.             {
  364. #if !SMP_TEST
  365.                 if (noErr == MPWaitOnSemaphore(gSemaphoreID, 33 * kDurationMillisecond))
  366.                     break;
  367. #endif !SMP_TEST
  368.  
  369. #if TARGET_API_MAC_CARBON
  370.                 GetGlobalMouse(&mousePoint);
  371. #else
  372.                 mousePoint = LMGetMouseLocation();
  373. #endif TARGET_API_MAC_CARBON
  374.                 if (oldMousePoint.v != mousePoint.v || oldMousePoint.h != mousePoint.h)
  375.                 {
  376.                     oldMousePoint = mousePoint;
  377.                     break;
  378.                 }
  379.             }
  380.  
  381.         } while (gPaused && gLoop);
  382.     } while (gLoop);
  383.  
  384.     return noErr;
  385. }
  386.  
  387. /**\
  388. |**|    Blit All
  389. \**/
  390.  
  391. static void Blit_All(void)
  392. {
  393.     SInt32 srcIndex,dstIndex;
  394.  
  395. #if TARGET_API_MAC_CARBON
  396.     GetGlobalMouse(&gMidPoint);
  397. #else
  398.     gMidPoint = LMGetMouseLocation();
  399. #endif TARGET_API_MAC_CARBON
  400.  
  401.     for (dstIndex = 0;dstIndex < 8;dstIndex++)
  402.     {
  403.         if (gMyGDInfoRec[dstIndex].fGDHdl)
  404.         {
  405.             Rect dstRect = gDstRect;
  406.  
  407.             if (Intersect_Rects(&gMyGDInfoRec[dstIndex].fRect,&dstRect))
  408.             {
  409.                 gDstPixMapHdl = gMyGDInfoRec[dstIndex].fPixMapHdl;
  410.                 gDstBaseAddr = gMyGDInfoRec[dstIndex].fBaseAddr;
  411.  
  412.                 Set_Rect(&gSrcRect,0,0,
  413.                     ((dstRect.right - dstRect.left) / gMag) + 1,
  414.                     ((dstRect.bottom - dstRect.top) / gMag) + 1);
  415.  
  416.                 Offset_Rect(&gSrcRect,
  417.                     gMidPoint.h - ((gSrcRect.left + gSrcRect.right) >> 1),
  418.                     gMidPoint.v - ((gSrcRect.top + gSrcRect.bottom) >> 1));
  419.  
  420.                 for (srcIndex = 0;srcIndex < 8;srcIndex++)
  421.                 {
  422.                     if (gMyGDInfoRec[srcIndex].fGDHdl)
  423.                     {
  424.                         Rect srcRect = gSrcRect;
  425.  
  426. //                        if (Intersect_Rects(&gMyGDInfoRec[srcIndex].fRect,&srcRect))
  427.                         if (Point2_In_Rect(gMidPoint.h,gMidPoint.v,&gMyGDInfoRec[srcIndex].fRect))
  428.                         {
  429.                             gSrcPixMapHdl = gMyGDInfoRec[srcIndex].fPixMapHdl;
  430.                             gSrcBaseAddr = gMyGDInfoRec[srcIndex].fBaseAddr;
  431.  
  432.                             Blit_One(&gSrcRect,&dstRect);
  433.                         }
  434.                     }
  435.                 }
  436.             }
  437.         }
  438.     }
  439. }
  440.  
  441. static void Blit_One(const Rect* pSrcRect,const Rect* pDstRect)
  442. {
  443.     if (gSrcPixMapHdl && gDstPixMapHdl)
  444.     {
  445.         Rect         srcBounds = (*gSrcPixMapHdl)->bounds;
  446.         UInt32         srcBytesPerPixel = (*gSrcPixMapHdl)->pixelSize / 8;
  447.         UInt32         srcSkip = (*gSrcPixMapHdl)->rowBytes & 0x3FFF;
  448.         Ptr         srcBase = gSrcBaseAddr +
  449.                         (srcSkip * (pSrcRect->top - srcBounds.top)) +
  450.                         ((pSrcRect->left - srcBounds.left) * srcBytesPerPixel);
  451.  
  452.         Rect         dstBounds = (*gDstPixMapHdl)->bounds;
  453.         UInt32         dstBytesPerPixel = (*gDstPixMapHdl)->pixelSize / 8;
  454.         UInt32         dstSkip = (*gDstPixMapHdl)->rowBytes & 0x3FFF;
  455.         Ptr         dstBase = gDstBaseAddr +
  456.                         (dstSkip * (pDstRect->top - dstBounds.top)) +
  457.                         ((pDstRect->left - dstBounds.left) * dstBytesPerPixel);
  458.  
  459.         SInt32 dstRow,dstCol,srcRow,srcCol,magRow,magCol;
  460.  
  461.         magRow = 0;
  462.         srcRow = pSrcRect->top;
  463.         for (dstRow = pDstRect->top;dstRow < pDstRect->bottom;dstRow++)
  464.         {
  465.             Ptr srcPtr = srcBase,dstPtr = dstBase;
  466.             UInt32    color32 = -1;
  467.             UInt16    color16 = -1;
  468.             UInt8     color8 = -1;
  469.  
  470.             magCol = 0;
  471.             srcCol = pSrcRect->left;
  472.             for (dstCol = pDstRect->left;dstCol < pDstRect->right;dstCol++)
  473.             {
  474.                 if (!magCol)
  475.                 {
  476.                     if ((srcRow >= srcBounds.top) &&
  477.                         (srcRow < srcBounds.bottom) &&
  478.                         (srcCol >= srcBounds.left) &&
  479.                         (srcCol < srcBounds.right))
  480.                     {
  481.                         color32 = *(UInt32*) srcPtr;
  482.                         color16 = color32 >> 16;
  483.                         color8 = color16 >> 8;
  484.                     }
  485.                     else
  486.                         color32 = color16 = color8 = 0;
  487.  
  488.                     srcPtr += srcBytesPerPixel;
  489.                     srcCol++;
  490.                 }
  491.  
  492.                 if ((dstRow >= dstBounds.top) &&
  493.                     (dstRow < dstBounds.bottom) &&
  494.                     (dstCol >= dstBounds.left) &&
  495.                     (dstCol < dstBounds.right))
  496.                 {
  497.                     switch (dstBytesPerPixel)
  498.                     {
  499.                         case 1:        // 256 colors
  500.                             *dstPtr = color8;
  501.                             break;
  502.                         case 2:    // thousand colors
  503.                             *(UInt16*) dstPtr = color16;
  504.                             break;
  505.                         case 4:    // million colors
  506.                             *(UInt32*) dstPtr = color32;
  507.                             break;
  508.                     }
  509.                 }
  510.                 dstPtr += dstBytesPerPixel;
  511.  
  512.                 magCol++;
  513.                 magCol %= gMag;
  514.             }
  515.             magRow++;
  516.             magRow %= gMag;
  517.             if (!magRow)
  518.             {
  519.                 srcBase += srcSkip;
  520.                 srcRow++;
  521.             }
  522.             dstBase += dstSkip;
  523.         }
  524.     }
  525. }
  526.  
  527. /**\
  528. |**|    Test to see if a point is in a rect
  529. \**/
  530.  
  531. static Boolean Point2_In_Rect(const short pH,const short pV,const Rect* pRect)
  532. {
  533.     if (pV < pRect->top)
  534.         return false;
  535.     if (pV >= pRect->bottom)
  536.         return false;
  537.     if (pH < pRect->left)
  538.         return false;
  539.     if (pH >= pRect->right)
  540.         return false;
  541.     return true;
  542. }
  543.  
  544. static void Set_Rect(Rect *r,
  545.     const short pLeft,
  546.     const short pTop,
  547.     const short pRight,
  548.     const short pBottom)
  549. {
  550.     r->top = pTop;
  551.     r->right = pRight;
  552.     r->bottom = pBottom;
  553.     r->left = pLeft;
  554. }
  555.  
  556. /**\
  557. |**|    aBool = SectRect(src1,src2,dstRect);
  558. \**/
  559.  
  560. static Boolean Intersect_Rects(const Rect* pRect1,Rect* pRect2)
  561. {
  562.     if (pRect2->top < pRect1->top)
  563.         pRect2->top = pRect1->top;
  564.  
  565.     if (pRect2->bottom > pRect1->bottom)
  566.         pRect2->bottom = pRect1->bottom;
  567.  
  568.     if (pRect2->left < pRect1->left)
  569.         pRect2->left = pRect1->left;
  570.  
  571.     if (pRect2->right > pRect1->right)
  572.         pRect2->right = pRect1->right;
  573.  
  574.     if ((pRect2->top < pRect2->bottom) &&
  575.         (pRect2->left < pRect2->right))
  576.         return true;
  577.     else
  578.         return false;
  579. }
  580.  
  581. /**\
  582. |**|    move a rectangle
  583. \**/
  584.  
  585. static void Offset_Rect(Rect *r,const short pDh,const short pDv)
  586. {
  587.     r->top += pDv;
  588.     r->left += pDh;
  589.     r->bottom += pDv;
  590.     r->right += pDh;
  591. }
  592.  
  593. /**\
  594. |**|    generate a random number +/- 32768
  595. \**/
  596.  
  597. static SInt16 random()
  598. {
  599.     static SInt32 state = 314159;
  600.  
  601.     state = ((state * 1103515245) + 12345 ) & 0x7fffffff;
  602.  
  603.     return ((state >> 6) & 0xffff);
  604. }
  605.  
  606.